﻿using ArtMath.Attribute;
using ArtMath.Component.Line;
using ArtMath.Component.Point;
using ArtMath.Core.Data;
using ArtMath.Core.Helper;
using ArtMath.Data;
using ArtMath.PointCollection;
using ArtMath.Resource;
using ArtMath.Setting;
using System;
using System.ComponentModel;
using System.Drawing;
using ArtMath.CommonType;

namespace ArtMath.Component.CoordinateSystem
{
    /// <summary>
    /// 直角坐标系
    /// </summary>
    [Serializable]
    public class RectangularCoordinate : CoordinateBase
    {
        bool showxOy = true;
        XAxis xz;
        YAxis yz;
        public RectangularCoordinate(SketchPad pad) : base(pad, Resources.Translate("RectangularCoordinate"), ToolTypeName.zjzbx)
        {

        }
        public override PointCollectionsManager Skeleton
        {
            get
            {
                PointCollectionsManager res = new PointCollectionsManager();
                res.AddPointCollection(XAxis.Skeleton);
                res.AddPointCollection(YAxis.Skeleton);
                return res;
            }
        }
        public override PointCollectionsManager PSkeleton
        {
            get
            {
                PointCollectionsManager res = new PointCollectionsManager();
                res.AddPointCollection(XAxis.PSkeleton);
                res.AddPointCollection(YAxis.PSkeleton);
                return res;
            }
        }
        public override PointCollectionsManager NewSkeleton
        {
            get
            {
                PointCollectionsManager res = new PointCollectionsManager();
                res.AddPointCollection(XAxis.NewSkeleton);
                res.AddPointCollection(YAxis.NewSkeleton);
                return res;
            }
        }
        public override PointCollectionsManager NewPSkeleton
        {
            get
            {
                PointCollectionsManager res = new PointCollectionsManager();
                res.AddPointCollection(XAxis.NewPSkeleton);
                res.AddPointCollection(YAxis.NewPSkeleton);
                return res;
            }
        }
        [MultilingualDisplayName("RectangularCoordinateOrigin")]
        public override PointBase OriginPoint
        {
            get
            {
                return base.OriginPoint;
            }

            set
            {
                base.OriginPoint = value;
            }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("XAxis")]
        public XAxis XAxis
        {
            get { return xz; }
            set
            {
                xz?.InHosts.Remove(this);
                xz = value;
                xz?.InHosts.Add(this);
            }
        }
        [MultilingualCategory("Structure"), MultilingualDisplayName("YAxis")]
        public YAxis YAxis
        {
            get { return yz; }
            set
            {
                yz?.InHosts.Remove(this);
                yz = value;
                yz?.InHosts.Add(this);
            }
        }
        [MultilingualCategory("View"), DefaultValue(typeof(bool), "True"), MultilingualDisplayName(null, "Show", "xOy"), TypeConverter(typeof(ArtMath.Converter.BooleanConverter))]
        public bool ShowxOy
        {
            get { return showxOy; }
            set
            {
                showxOy = value;
                Pad.Canvas.Invalidate();
            }
        }
        [MultilingualDisplayName("OriginPosition")]
        public override RPointS OriginCoordinate
        {
            get
            {
                return base.OriginCoordinate;
            }

            set
            {
                base.OriginCoordinate = value;
            }
        }
        public override void ForEachStraightLine(Predicate<StraightLineBase> act)
        {
            if (act == null) return;
            if (!act(XAxis)) return;
            act(YAxis);
        }
        public override void RotateAngleChanged(double oldValue)
        {
            base.RotateAngleChanged(oldValue);
            xz.PSlope = Math.Tan(-RotateAngle.RadValue);
            yz.PSlope = Math.Tan(-RotateAngle.RadValue - Core.Helper.Angle.RightAngle);
        }
        //public override bool Selected_
        //{
        //    get
        //    {
        //        return base.Selected_;
        //    }

        //    set
        //    {
        //        base.Selected_ = value;
        //        if (XAxis != null)
        //        {
        //            XAxis.Selected_ = Selected_;
        //        }
        //        if (YAxis != null)
        //        {
        //            YAxis.Selected_ = Selected_;
        //        }
        //    }
        //}
        //public override StyleState StyleState_
        //{
        //    get
        //    {
        //        return base.StyleState_;
        //    }

        //    set
        //    {
        //        base.StyleState_ = value;
        //        if (XAxis != null)
        //        {
        //            XAxis.StyleState_ = StyleState_;
        //        }
        //        if (YAxis != null)
        //        {
        //            YAxis.StyleState_ = StyleState_;
        //        }
        //    }
        //}
        public override void InChildrenIterator(Predicate<ShapeBase> act)
        {
            if (act == null) return;
            if (XAxis != null)
            {
                if (!act(XAxis)) return;
            }
            if (YAxis != null)
            {
                if (!act(YAxis)) return;
            }
            //base.InChildrenIterator(act);
        }
        //public override bool Visible
        //{
        //    get
        //    {
        //        return base.Visible;
        //    }

        //    set
        //    {
        //        base.Visible = value;
        //        if (XAxis != null) XAxis.Visible = Visible;
        //        if (YAxis != null) YAxis.Visible = Visible;
        //    }
        //}
        protected override double ScaleX
        {
            get
            {
                return XAxis.Scale.Value;
            }
        }
        protected override double ScaleY
        {
            get
            {
                return YAxis.Scale.Value;
            }
        }
        protected override double UnitX
        {
            get
            {
                return XAxis.Unit.Value;
            }
        }
        protected override double UnitY
        {
            get
            {
                return YAxis.Unit.Value;
            }
        }
        //public override PointD[] GetCrossPoints(ShapeBase shape, bool getNew = true)
        //{
        //    List<PointD> res = new List<PointD>();
        //    PointD[] pts = XAxis.GetCrossPoints(shape, getNew);
        //    if (pts != null) res.AddRange(pts);
        //    pts = YAxis.GetCrossPoints(shape, getNew);
        //    if (pts != null) res.AddRange(pts);
        //    if (res.Count == 0) return null;
        //    return res.ToArray();
        //}
        //protected override void SetChildrenLinesColor()
        //{
        //    if (XAxis != null)
        //    {
        //        XAxis.LineColor = LineColor;
        //    }
        //    if (YAxis != null)
        //    {
        //        YAxis.LineColor = LineColor;
        //    }
        //    base.SetChildrenLinesColor();
        //}
        //protected override void SetChildrenLinesDashStyle()
        //{
        //    if (XAxis != null)
        //    {
        //        XAxis.LineDashStyle = LineDashStyle;
        //    }
        //    if (YAxis != null)
        //    {
        //        YAxis.LineDashStyle = LineDashStyle;
        //    }
        //    base.SetChildrenLinesDashStyle();
        //}
        //protected override void SetChildrenLinesWidth()
        //{
        //    if (XAxis != null)
        //    {
        //        XAxis.LineWidth.SetExpression(LineWidth.Expression);
        //    }
        //    if (YAxis != null)
        //    {
        //        YAxis.LineWidth.SetExpression(LineWidth.Expression);
        //    }
        //    base.SetChildrenLinesWidth();
        //}
        public override void CoordinateChanged(PointsRelocationReason reason)
        {
            if (Pad.Location.X + OriginCoordinate.X < 24)
            {
                YAxis.GraduationTextLocation = AxisTextLocation.Below;
            }
            else
            {
                YAxis.GraduationTextLocation = AxisTextLocation.Above;
            }
            if (Pad.Location.Y + OriginCoordinate.Y > Pad.Canvas.Height - 25)
            {
                XAxis.GraduationTextLocation = AxisTextLocation.Above;
            }
            else
            {
                XAxis.GraduationTextLocation = AxisTextLocation.Below;
            }
            base.CoordinateChanged(reason);
        }
        //public override void CheckInRegion(RectangleD rect)
        //{
        //    XAxis.CheckInRegion(rect);
        //    YAxis.CheckInRegion(rect);
        //    base.CheckInRegion(rect);
        //}
        public override void RotateCenter_CoordinateChanged(PointD oldValue, PointD newValue)
        {
            rotatePCenter = XYToPxy(RotateCenter.ToPointD()) + OriginCoordinate.ToPointD();
        }
        public override void Paint(Graphics gra)
        {
            if (ObjectState == ObjectState.Normal && Visible)
            {
                gra.RotateTransform((float)-RotateAngle.DegreeValue);
                YAxis.Paint(gra);
                XAxis.Paint(gra);
                System.Drawing.Point location = new System.Drawing.Point(0, 0);
                if ((XAxis.Visible && XAxis.ShowGraduation || YAxis.Visible && YAxis.ShowGraduation) && XAxis.Visible && YAxis.Visible)
                {
                    if (showxOy)
                    {
                        location = new System.Drawing.Point(-30, 4);
                    }
                    else
                    {
                        location = new System.Drawing.Point(-22, 6);
                    }
                }
                else if (XAxis.Visible && XAxis.ShowGraduation && !YAxis.Visible)
                {
                    if (showxOy)
                    {
                        location = new System.Drawing.Point(-14, 4);
                    }
                    else
                    {
                        location = new System.Drawing.Point(-9, 6);
                    }
                }
                else if (YAxis.Visible && YAxis.ShowGraduation && !XAxis.Visible)
                {
                    if (showxOy)
                    {
                        location = new System.Drawing.Point(-30, -15);
                    }
                    else
                    {
                        location = new System.Drawing.Point(-22, -11);
                    }
                }
                if (location.X != location.Y)//当x=y(=0)时就不显示“0”
                {
                    Color cl = Settings.Instance.DisableReversedColorWhenEqualsPadBGColor && Pad.BackgroundColor.BaseColorEquals(Color.White) ? Color.Black : Color.White;
                    if (showxOy)
                    {
                        gra.DrawString("O", new Font("Times New Roman", 20, FontStyle.Italic), new SolidBrush(StyleState_ == StyleState.Hover || Selected && Pad.UseReversedColor ? cl : Color.Black), location);
                    }
                    else
                    {
                        gra.DrawString("0", new Font("Times New Roman", 16), new SolidBrush(StyleState_ == StyleState.Hover || Selected && Pad.UseReversedColor ? cl : Color.Black), location);
                    }
                }
                gra.RotateTransform((float)RotateAngle.DegreeValue);
            }
            base.Paint(gra);
        }
        public override void CreateComponents()
        {
            XAxis = new XAxis(Pad);
            YAxis = new YAxis(Pad);
            OriginPoint = new RectangularCoordinateOriginPoint(Pad);
            Pad.TryCreateObject(OriginPoint);
            XAxis.CreateComponents();
            XAxis.SetPoint(0, OriginPoint);
            YAxis.CreateComponents();
            YAxis.SetPoint(0, OriginPoint);
            base.CreateComponents();
        }

        public override void UseFormat(Base obj)
        {
            base.UseFormat(obj);
            PolarCoordinate pc = obj as PolarCoordinate;
            if (pc != null)
            {
                if (Settings.Instance.ViewUseFormat)
                {
                    ShowxOy = pc.ShowOx;
                }
                if (Settings.Instance.InChildrenUseFormat)
                {
                    XAxis.UseFormat(pc.PolarAxis);
                    YAxis.UseFormat(pc.PolarAxis);
                }
            }
        }
        //public override Base[] CheckNearBy(PointD Plocation)
        //{
        //    List<Base> objs = new List<Base>(base.CheckNearBy(Plocation));
        //    objs.AddRange(XAxis.CheckNearBy(Plocation));
        //    objs.AddRange(YAxis.CheckNearBy(Plocation));
        //    return objs.ToArray();
        //}
    }
}
